/**
 * Copyright (C) 2008 Happy Fish / YuQing
 * <p>
 * FastDFS Java Client may be copied only under the terms of the GNU Lesser
 * General Public License (LGPL).
 * Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
 **/

package org.csource.common;

import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.Hashtable;

/**
 * ini file reader / parser
 *
 * @author Happy Fish / YuQing
 * @version Version 1.0
 */
public class IniFileReader {
  private Hashtable<String,Object> paramTable;
  private String conf_filename;

  /**
   * @param conf_filename config filename
   */
  public IniFileReader(String conf_filename) throws IOException {
    this.conf_filename = conf_filename;
    loadFromFile(conf_filename);
  }

  public static ClassLoader classLoader() {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    if (loader == null) {
      loader = ClassLoader.getSystemClassLoader();
    }
    return loader;
  }

	public static InputStream loadFromOsFileSystemOrClasspathAsStream(String filePath) {
		InputStream in = null;
		String fileName = null;
		try {
			if(filePath!=null&&filePath.trim().length()>0) {
				//将反斜杠替换为正斜杠
				filePath=filePath.replaceAll("\\\\", "/");
				int lastXg=filePath.lastIndexOf("/");
				if(lastXg!=-1) {
					fileName=filePath.substring(lastXg+1);
				}else {
					fileName=filePath;
				}
				// 优先从文件系统路径加载
				if (new File(filePath).exists()) {
					in = new FileInputStream(filePath);
					System.out.println("loadFrom resource= ".concat(filePath));
				}
				// 从类路径加载
				else {
					//获取classloader加载路径
					String sourceFile=classLoader().getResource("").getPath();
					System.out.println("lassLoader path= ".concat(sourceFile));
					//判断启动方式是否以jar包方式启动
					int jarIndex=sourceFile.indexOf(".jar");
					//如果是jar方式启动
					if(jarIndex!=-1) {
						//获取jar包对应的path路径
						sourceFile=sourceFile.substring(0, jarIndex+4);
						File jarFile=new File(new URI(sourceFile));
						if (jarFile.exists()) {
							String projectPath=jarFile.getParentFile().getAbsolutePath();
							//获取配置文件名称
							File confgFile=new File(projectPath.concat("/config/").concat(fileName));
							if(confgFile.exists()) {
								in = new FileInputStream(confgFile);
								System.out.println("loadFrom jar config= ".concat(projectPath.concat("/config/")));
								if (in != null) {
								    return in;
								}
							}
						}
					}
					//tomcat方式启动
					int webInf=sourceFile.indexOf("/WEB-INF/");
					if(webInf!=-1) {
					    //截取到tomcat根路径
					    sourceFile=sourceFile.substring(0, webInf);
					    File webInfFile=new File(sourceFile);
					    if(webInfFile.exists()) {
					        ///apache-tomcat-pageoffice/webapps/ROOT/WEB-INF/classes/   webapps路径下config优先
					        String tomcatConfigPath=webInfFile.getParentFile().getAbsolutePath().concat("/config/").concat(fileName);
					        //获取配置文件名称
					        File confgFile=new File(tomcatConfigPath);
					        if(confgFile.exists()) {
					            in = new FileInputStream(confgFile);
					            System.out.println("loadFrom tomcat config= ".concat(tomcatConfigPath));
					            if (in != null) {
					                return in;
					            }
					        }
					        //tomcat webapps路径下的配置文件 tomcat目录下config优先级低
					        String webappsConfigPath=webInfFile.getParentFile().getParentFile().getAbsolutePath().concat("/config/").concat(fileName);
					        //获取配置文件名称
					        confgFile=new File(webappsConfigPath);
					        if(confgFile.exists()) {
					            in = new FileInputStream(confgFile);
					            System.out.println("loadFrom tomcat config= ".concat(webappsConfigPath));
					            if (in != null) {
					                return in;
					            }
					        }
					    }
					}
					in = classLoader().getResourceAsStream(filePath);
					System.out.println("loadFrom= ".concat(classLoader().getResource(filePath).toString()));
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return in;
	}

  /**
   * get the config filename
   *
   * @return config filename
   */
  public String getConfFilename() {
    return this.conf_filename;
  }

  /**
   * get string value from config file
   *
   * @param name item name in config file
   * @return string value
   */
  @SuppressWarnings("rawtypes")
public String getStrValue(String name) {
    Object obj;
    obj = this.paramTable.get(name);
    if (obj == null) {
      return null;
    }

    if (obj instanceof String) {
      return (String) obj;
    }

    return (String) ((ArrayList) obj).get(0);
  }

  /**
   * get int value from config file
   *
   * @param name          item name in config file
   * @param default_value the default value
   * @return int value
   */
  public int getIntValue(String name, int default_value) {
    String szValue = this.getStrValue(name);
    if (szValue == null) {
      return default_value;
    }

    return Integer.parseInt(szValue);
  }

  /**
   * get boolean value from config file
   *
   * @param name          item name in config file
   * @param default_value the default value
   * @return boolean value
   */
  public boolean getBoolValue(String name, boolean default_value) {
    String szValue = this.getStrValue(name);
    if (szValue == null) {
      return default_value;
    }

    return szValue.equalsIgnoreCase("yes") || szValue.equalsIgnoreCase("on") ||
      szValue.equalsIgnoreCase("true") || szValue.equals("1");
  }

  /**
   * get all values from config file
   *
   * @param name item name in config file
   * @return string values (array)
   */
  public String[] getValues(String name) {
    Object obj;
    String[] values;

    obj = this.paramTable.get(name);
    if (obj == null) {
      return null;
    }

    if (obj instanceof String) {
      values = new String[1];
      values[0] = (String) obj;
      return values;
    }

    Object[] objs = ((ArrayList) obj).toArray();
    values = new String[objs.length];
    System.arraycopy(objs, 0, values, 0, objs.length);
    return values;
  }

  private void loadFromFile(String confFilePath) throws IOException {
    InputStream in = loadFromOsFileSystemOrClasspathAsStream(confFilePath);
    try {
      readToParamTable(in);
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      try {
        if (in != null) in.close();
        //System.out.println("loadFrom...finally...in.close(); done");
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }

  private void readToParamTable(InputStream in) throws IOException {
    this.paramTable = new Hashtable();
    if (in == null) return;
    String line;
    String[] parts;
    String name;
    String value;
    Object obj;
    ArrayList valueList;
    InputStreamReader inReader = null;
    BufferedReader bufferedReader = null;
    try {
      inReader = new InputStreamReader(in);
      bufferedReader = new BufferedReader(inReader);
      while ((line = bufferedReader.readLine()) != null) {
        line = line.trim();
        if (line.length() == 0 || line.charAt(0) == '#') {
          continue;
        }
        parts = line.split("=", 2);
        if (parts.length != 2) {
          continue;
        }
        name = parts[0].trim();
        value = parts[1].trim();
        obj = this.paramTable.get(name);
        if (obj == null) {
          this.paramTable.put(name, value);
        } else if (obj instanceof String) {
          valueList = new ArrayList();
          valueList.add(obj);
          valueList.add(value);
          this.paramTable.put(name, valueList);
        } else {
          valueList = (ArrayList) obj;
          valueList.add(value);
        }
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      try {
        if (bufferedReader != null) bufferedReader.close();
        if (inReader != null) inReader.close();
        //System.out.println("readToParamTable...finally...bufferedReader.close();inReader.close(); done");
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }

}
